package cn.gdchent.springbootsecurity.encrypt;

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.Arrays;
import java.util.Base64;
import java.util.Objects;

public final class Encryptors {

	private Encryptors() {
		throw new AssertionError("No com.populus.springboot.encrypt.Encryptors.Encryptors instance for you!");
	}
	
	static final SecureRandom SECURE_RANDOM = new SecureRandom();
	static final int LEN = 16;

	static MessageDigest messageDigest;

	static {
		try {
			messageDigest = MessageDigest.getInstance("MD5");
		} catch (NoSuchAlgorithmException e) {
			throw new AssertionError(e);
		}
	}

	public static byte[] encryptBytes(String password) {
		Objects.requireNonNull(password);
		byte[] salt = new byte[LEN];
		SECURE_RANDOM.nextBytes(salt);
		messageDigest.update(salt);
		messageDigest.update(password.getBytes());
		byte[] digest = messageDigest.digest();

		byte[] encryptBytes = new byte[LEN + digest.length];
		System.arraycopy(salt, 0, encryptBytes, 0, LEN);
		System.arraycopy(digest, 0, encryptBytes, LEN, digest.length);

		return encryptBytes;
	}

	public static String encrypt(String password) {
		return Base64.getEncoder().encodeToString(encryptBytes(password));
	}

	public static boolean validate(String password, String encrypt) {
		return (password != null) && (encrypt != null) && verify(password, encrypt);
	}

	private static boolean verify(String password, String encrypt) {
		byte[] decode = Base64.getDecoder().decode(encrypt);
		byte[] salt = Arrays.copyOf(decode, LEN);
		messageDigest.update(salt);
		messageDigest.update(password.getBytes());
		byte[] digest = messageDigest.digest();
		byte[] encryptBytes = Arrays.copyOfRange(decode, LEN, decode.length);

		return Arrays.equals(digest, encryptBytes);
	}

}
